#ifndef _FILESYSTEM_H
#define _FILESYSTEM_H

#include <stdio.h>
#include <stdint.h>

#include "bib_Comunicacion.h"
#include "bib_Estructuras_de_datos.h"
#include "utils.h"

typedef struct bootSector{

    uint8_t jumpInstruction[3];
    uint8_t oemName[8];
    uint16_t bytesPerSector;
    uint8_t sectorsPerCluster;
    uint16_t reservedSectorCount;
    uint8_t numberOfFats;
    uint16_t rootDirectoryMaxEntries;
    uint16_t totalSectors;
    uint8_t mediaDescriptor;
    uint16_t sectorsPerFat12_16;
    uint16_t sectorsPerTrack;
    uint16_t numberOfHeads;
    uint32_t countOfHiddenSectors;
    uint32_t totalSectors2;
    uint32_t sectorsPerFat;
    uint16_t mirroringFlags;
    uint16_t version;
    uint32_t firstClusterOfRootDirectory;
    uint16_t sectorNumberOfFsInfSector;
    uint16_t fstSectorOfCopyFat32Bs;
    uint8_t reserved[12];
    uint8_t physicalDriveNumber;
    uint8_t unusedSector;
    uint8_t extendedBootSignature;
    uint32_t volumeId;
    uint8_t volumeLabel[11];
    uint8_t fileSystemType[8];
    uint8_t osBootCode[420];
    uint16_t bootSectorSignature;
} __attribute__((packed)) bootSector;

typedef struct fsInformationSector{

    uint32_t fsInfoSectorSignature;
    uint8_t reserved[480];
    uint32_t fsInfoSectorSignature2;
    uint32_t numberOfFreeClusters;
    uint32_t mostRecentlyAllocatedCluster;
    uint8_t reserved2[12];
    uint32_t fsInfoSectorSignature3;
} __attribute__((packed)) fsInformationSector;

typedef struct bsUtil{

    uint16_t bytesPerSector;
    uint8_t sectorsPerCluster;
    uint16_t reservedSectorCount;
    uint8_t numberOfFats;
    uint16_t totalSectors;
    uint32_t totalSectors2;
    uint32_t sectorsPerFat;
    uint32_t firstClusterOfRootDirectory;
    uint16_t sectorNumberOfFsInfSector;
    uint32_t numberOfFreeClusters;
    uint32_t mostRecentlyAllocatedCluster;
    uint32_t totalClusters;
    uint32_t tamBitMap;
    uint32_t EOC;
}bsUtil;

typedef struct directoryTableEntry{

    uint8_t dosFileName[8];
    uint8_t dosFileExtension[3];
    uint8_t fileAttributes;
    uint8_t reserved;
    uint8_t createTime;
    uint16_t createTime2;
    uint16_t createDate;
    uint16_t lastAccessDate;
    uint16_t startFileCluster;
    uint16_t lastModifiedTime;
    uint16_t lastModifiedDate;
    uint16_t startFileCluster2;
    uint32_t fileSize;
} __attribute__((packed)) directoryTableEntry;

typedef struct lfnEntry{

    uint8_t secuenceNumber;
    uint16_t nameCharacters[5];
    uint8_t Attributes;
    uint8_t reserved;
    uint8_t checkSum;
    uint16_t nameCharacters2[6];
    uint16_t firstCluster;
    uint16_t nameCharacters3[2];
} __attribute__((packed)) lfnEntry;



int getBootSector( bootSector **bs, fsInformationSector **fsIs);/*Test OK*/
int procesarBootSector( bootSector **bs, fsInformationSector **fsIs);/*Test OK*/
int crearFAT( void);/*Test OK*/
int crearBitMap( void);/*Test OK*/
int inicializarFATyBitMap( void);/*Test OK*/
int delFAT( void);/*Test OK*/
int delBitMap( void);/*Test OK*/
int getDirectoryTable( directoryTableEntry **dirTable, char *idBloque,uint32_t numCluster);
uint32_t recorrerPath( char *path, uint32_t numCluster);
void armarListaDir( directoryTableEntry *dirTable, struct lstDirTable **lista);
void readDirEntry( directoryTableEntry *bufDirEntry, struct tDirEntry *dirEntry);
void readLFNEntry( struct lfnEntry *bufDirEntry, struct tDirEntry *dirEntry);
int buscarArchEnLista( char *nombreArchivo, struct lstDirTable *listaArchivos, struct tDirEntry *archivo);
int liberarListaArchivos( struct lstDirTable *listaArchivos);
int listarPath( char *path, struct lstDirTable **listaArchivos);
int obtenerNombreDeArchivo( char *path, char *nombreArchivo);
int obtenerInfoArchivo( char *path, struct tDirEntry *archivo);
int ultClusterArch( uint32_t firstCluster, uint32_t *lastCluster); /*	*lastCluster = 0	si filesize == 0*/
int recorrerXClustersArch( uint32_t firstCluster, uint32_t nuevaCantClusters, uint32_t *ultCluster);
int actualizarTamanioArchEnFAT( size_t size, uint32_t nroCluster, uint32_t posRelCluster, char *nombreArchivo);

#endif
